home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
DDJMAG
/
DDJ8802.ZIP
/
LINDLEY.ZIP
/
LINDLEY.LS3
< prev
next >
Wrap
Text File
|
1980-01-01
|
10KB
|
485 lines
{************************************************}
{*** ***}
{*** RS-232 support procedures ***}
{*** for the serial protocol analyzer ***}
{*** written by ***}
{*** Craig A. Lindley ***}
{*** ***}
{*** Ver: 2.0 Last update: 08/15/87 ***}
{*** ***}
{************************************************}
CONST
COM1 = $3f8; {com one port addr}
COM2 = $2f8; {com two port addr}
{table of values for the various baud rates}
{supported by the 8250. Rates from 50..9600}
BaudRate: ARRAY[1..15] OF Integer =
($900,$600,$417,$359,$300,$180,$0C0,$060,
$040,$03A,$030,$020,$018,$010,$00C);
{8259 registers}
Int_Mask_Reg = $21; {interrupt enable register}
Int_Cmd_Reg = $20; {command register}
End_Int_Cmd = $20; {end of interrupt cmd}
{offsets from PortAddr for the various}
{8250 registers}
DLL = 0;
DLM = 1;
Int_Enable_Reg = 1;
Int_Id_Reg = 2;
LineControl = 3;
ModemControl = 4;
LineStatus = 5;
ModemStatus = 6;
{Status bit definitions}
DataRdyBit = $01;
DTRBit = $01;
Out2Bit = $08;
ORBit = $01;
RTSBit = $02;
PEBit = $02;
FEBit = $04;
BrkBit = $08;
CTSBit = $10;
DSRBit = $20;
TxRdyBit = $20;
RIBit = $40;
CDBit = $80;
TYPE
ParityType = (odd,even,none);
VAR
{Global storage of COM parameters}
{Used by the SetNewCOMParameter}
{procedure}
COM_Rate,
COM_StopBits,
COM_DataBits: Integer;
COM_Parity: ParityType;
{************** Serial Procedures ***************}
PROCEDURE Enable_Serial_Device (PortAddr:Integer);
VAR
Temp: Byte;
BEGIN
{clear the 8250 serial device of any garbage}
{by reading data port, int id reg. line}
{status reg and modem status reg}
Temp := port[PortAddr];
Temp := port[PortAddr+Int_Id_Reg];
Temp := port[PortAddr+LineStatus];
Temp := port[PortAddr+ModemStatus];
{read 8259 int mask reg and set IRQ3 or IRQ4}
{low to enable requested interrupts.}
{write result back to 8259 when finished}
Temp := port[Int_Mask_Reg];
IF PortAddr = COM1 THEN
Temp := Temp AND $EF
ELSE
Temp := Temp AND $F7;
port[Int_Mask_Reg] := Temp;
{Out2, DTR and RTS high for 8250}
port[PortAddr+ModemControl] :=
Out2Bit + DTRBit + RTSBit;
{all ints active except Tx}
port[PortAddr+Int_Enable_Reg] := $0D;
delay(100);
END;
PROCEDURE Disable_Serial_Devices;
VAR
Temp: Byte;
BEGIN
{Read int mask in 8259, set both IRQ3}
{and IRQ4 bits high to disable. Set Out2}
{low for both COM1 and COM2 to prevent ints}
{from leaving the async card and finally}
{disable all interrupt sources in the UART}
Temp := port[Int_Mask_Reg];
Temp := Temp OR $18;
port[Int_Mask_Reg] := Temp;
port[COM1+ModemControl] := 0;
port[COM2+ModemControl] := 0;
port[COM1+Int_Enable_Reg] := 0;
port[COM2+Int_Enable_Reg] := 0;
END;
PROCEDURE COM1_ISR;
{COM1 interrupt service routine}
VAR
SerialInfo: DataRec;
Temp: Integer;
LineState,
ModemState: Byte;
BEGIN
{read linestatus and modem status and}
{combine into COM1_Status. See text for}
{bit encoding.}
LineState := port[COM1+LineStatus];
ModemState:= port[COM1+ModemStatus];
Temp := (LineState SHR 1) AND $0F;
{COM1_Status has the UART state in 8 bits}
{this is comprised of status info only, no data}
COM1_Status := (ModemState AND $F0) OR lo(Temp);
{if there is data to receive and we are}
{acquiring data}
IF (((LineState AND DataRdyBit) <> 0) AND
COM1_Data_Acquire) THEN
BEGIN
{if there is room in the COM1 input fifo}
IF COM1_Input_Fifo.Ovd.Count <
SerialDataFifoSize THEN
BEGIN
{Put received data and status into fifo}
SerialInfo.Data := port[COM1];
SerialInfo.Status := COM1_Status;
PutSerialData(SerialInfo,COM1_Input_Fifo);
END
ELSE
BEGIN
writeln('COM1 Input fifo overflowed');
halt;
END;
END;
{signal end of int to 8259}
port[Int_Cmd_Reg] := End_Int_Cmd;
END;
PROCEDURE COM2_ISR;
{COM2 interrupt service routine}
VAR
SerialInfo: DataRec;
Temp: Integer;
LineState,
ModemState: Byte;
BEGIN
{read linestatus and modem status and}
{combine into COM2_Status. See text for}
{bit encoding.}
LineState := port[COM2+LineStatus];
ModemState:= port[COM2+ModemStatus];
Temp := (LineState SHR 1) AND $0F;
{COM2_Status has the UART state in 8 bits}
{this is comprised of status info only, no data}
COM2_Status := (ModemState AND $F0) OR lo(Temp);
{if there is data to receive and we are}
{acquiring data}
IF (((LineState AND DataRdyBit) <> 0) AND
COM2_Data_Acquire) THEN
BEGIN
{if there is room in the COM2 input fifo}
IF COM2_Input_Fifo.Ovd.Count <
SerialDataFifoSize THEN
BEGIN
{Put received data and status into fifo}
SerialInfo.Data := port[COM2];
SerialInfo.Status := COM2_Status;
PutSerialData(SerialInfo,COM2_Input_Fifo);
END
ELSE
BEGIN
writeln('COM2 Input fifo overflowed');
halt;
END;
END;
{signal end of int to 8259}
port[Int_Cmd_Reg] := End_Int_Cmd;
END;
PROCEDURE COM1_Int_Service_Routine;
BEGIN
INLINE($50/$53/$51/$52/$57/ {Push ax,bx,cx,dx,}
$56/$06/$1e/ {di,si,es,ds}
$2e/$a1/turbodseg/ {mov ax,cs:turbodseg}
$8e/$d8/ {mov ds,ax}
$fb); {sti}
COM1_ISR;
{standard interrupt service routine postamble}
INLINE($fa/$1f/$07/$5e/$5f/ {interrupts off}
$5a/$59/$5b/$58/ {Pop ds,es,si,di,}
{dx,cx,bx,ax}
$5d/$5d/$cf); {trash sp, restore}
{Bp and iret}
END;
PROCEDURE COM2_Int_Service_Routine;
BEGIN
INLINE($50/$53/$51/$52/$57/ {Push ax,bx,cx,dx,}
$56/$06/$1e/ {di,si,es,ds}
$2e/$a1/turbodseg/ {mov ax,cs:turbodseg}
$8e/$d8/ {mov ds,ax}
$fb); {sti}
COM2_ISR;
{standard interrupt service routine postamble}
INLINE($fa/$1f/$07/$5e/$5f/ {interrupts off}
$5a/$59/$5b/$58/ {Pop ds,es,si,di,}
{dx,cx,bx,ax}
$5d/$5d/$cf); {trash sp, restore}
{Bp and iret}
END;
PROCEDURE Install_Serial_Handlers;
BEGIN
WITH regs DO {install into IRQ3 & 4}
BEGIN
ah := $35; {get vector func. code}
al := $0B; {for IRQ3}
msdos(regs); {call dos to get vector}
OldIRQ3_CS := es;{save code seg}
OldIRQ3_IP := bx;{and instruction ptr}
ah := $35; {get vector func. code}
al := $0C; {for IRQ4}
msdos(regs); {call dos to get vector}
OldIRQ4_CS := es;{save code seg}
OldIRQ4_IP := bx;{and instruction ptr}
ah := $25; {set vector func. code}
al := $0C; {for IRQ4}
ds := cseg; {code in our segment}
{at this offset}
dx := ofs(COM1_Int_Service_Routine);
msdos(regs); {call dos to set vector}
ah := $25; {set vector func. code}
al := $0B; {for IRQ3}
ds := cseg; {code in our segment}
{at this offset}
dx := ofs(COM2_Int_Service_Routine);
msdos(regs); {call dos to set vector}
END;
END;
PROCEDURE Remove_Serial_Handlers;
BEGIN
{Put saved vectors for IRQ3 and IRQ4 back}
WITH regs DO
BEGIN
ah := $25;
al := $0C;
ds := OldIRQ4_CS;
dx := OldIRQ4_IP;
msdos(regs);
ah := $25;
al := $0B;
ds := OldIRQ3_CS;
dx := OldIRQ3_IP;
msdos(regs);
END;
END;
PROCEDURE Set_Serial_Parameters
(PortAddr,Baud,StopBits,DataBits:Integer;
Parity: ParityType);
VAR
Temp,
Rate: Integer;
BEGIN
{set DLAB high for divisor regs}
port[PortAddr+LineControl] := $80;
{look up rate word in table}
Rate := BaudRate[Baud];
{MSB into most sign divisor reg}
port[PortAddr+DLM] := hi(Rate);
{LSB into less sign divisor reg}
port[PortAddr+DLL] := lo(Rate);
{move databits into 2 least sign bits}
{add in stop bit into bit pos 2}
{set parity enable and parity even}
{bits if appropriate}
Temp := (DataBits - 5) AND $03;
Temp := Temp OR ((StopBits - 1) SHL 2);
CASE Parity OF
odd: Temp := Temp + $08;
even: Temp := Temp + $18;
none: ;
END;
{remove DLAB and setup parameters}
port[PortAddr+LineControl] := lo(Temp);
delay(100);
END;
FUNCTION Get_Serial_Status (PortAddr:Integer)
:Integer;
VAR
Temp: Integer;
BEGIN
{Get full 16 bits of COM port status}
{grouped as ModemStatus:LineStatus}
Temp := port[PortAddr+ModemStatus];
Temp := Temp SHL 8;
Temp := Temp OR port[PortAddr+LineStatus];
Get_Serial_Status := Temp;
END;
PROCEDURE SetNewCOMParameter;
BEGIN
{take the COM ports down}
Disable_Serial_Devices;
{Set the COM ports to the global parameters}
Set_Serial_Parameters(COM1,COM_Rate,
COM_StopBits,COM_DataBits,COM_Parity);
Set_Serial_Parameters(COM2,COM_Rate,
COM_StopBits,COM_DataBits,COM_Parity);
{bring COM ports back up}
Enable_Serial_Device(COM1);
Enable_Serial_Device(COM2);
END;